#
#  SocketServer.py
#  PyMol Plugin
#
#  Created by Christian Muise on 25/01/08.
#  Copyright (c) 2008 Christian Muise. All rights reserved.
#
"""
An echo server that uses threads to handle multiple clients at a time.
Entering any line of input at the terminal will exit the server.
"""

import select
import socket
import sys
import threading
import time

class Server(threading.Thread):
	def __init__(self, plugin_instance, port=4440):
		threading.Thread.__init__(self)
		self.host = ''
		self.port = port
		self.backlog = 5
		self.size = 1024
		self.server = None
		self.threads = []
		self.plugin = plugin_instance

	def open_socket(self):
		try:
			self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			self.server.bind((self.host,self.port))
			self.server.listen(5)
		except socket.error, (value,message):
			if self.server:
				self.server.close()
			print "Could not open socket: " + message
			sys.exit(1)

	def run(self):
		self.open_socket()
		input = [self.server]
		running = 1
		while running:
			inputready,outputready,exceptready = select.select(input,[],[])

			for s in inputready:

				if s == self.server:
					# handle the server socket
					if (self.port == 4440):
						c = Client(self.server.accept(), self.plugin, 'Tracking')
						
					elif (self.port == 4441):
						c = Client(self.server.accept(), self.plugin, 'GUI')
						
					c.start()
					self.threads.append(c)

				elif s == sys.stdin:
					# handle standard input
					junk = sys.stdin.readline()
					running = 0

		# close all threads

		self.server.close()
		for c in self.threads:
			c.join()

class Client(threading.Thread):
	def __init__(self,(client,address), plugin_instance, name):
		threading.Thread.__init__(self)
		self.client = client
		self.address = address
		self.size = 1024
		self.plugin = plugin_instance
		self.frame_count = 0
		self.timestamp = time.time()
		self.name = name
		self.do_fps = 1
		
		if self.name == 'GUI':
			self.do_fps = 0

	def run(self):
		running = 1
		print str(self.name) + " Server Running..."
		while running:
			data = self.client.recv(self.size)
			if data:
				
				# Deal with the frame rate
				if self.do_fps:
					self.plugin.set_data(data)
				
					self.frame_count += 1
					if (self.frame_count == 50):
						self.frame_count = 0
						new_time = time.time()
						fps = 50 / (new_time - self.timestamp)
						self.plugin.set_fps_in(fps)
						self.timestamp = new_time
						
				else:
					self.plugin.set_change(data)
			else:
				self.client.close()
				running = 0 

if __name__ == "__main__":
	s = Server(13)
	s.run()
